/**
 * 作者: wgx
 * 日期: 2024-10-15 15:22:18
 * 备注: 用户伙伴表
 */
package com.motu.monstercity.server.game.userdata;

import com.motu.monstercity.module.common.utility.Constant;
import com.motu.monstercity.protocol.Common.PBUserData;
import com.motu.monstercity.protocol.Common.PBUserPartner;
import com.motu.monstercity.protocol.Common.PBWeaponAtt;
import com.motu.monstercity.server.game.base.CommonUtils;
import com.motu.monstercity.server.game.base.GameConstant;
import com.motu.monstercity.server.game.commondata.act.ActTopRanking;
import com.motu.monstercity.server.game.commondata.maintask.MainTaskConstant;
import com.motu.monstercity.server.game.commondata.partner.*;
import com.motu.monstercity.server.game.commondata.skill.SkillConstant;
import com.motu.monstercity.server.game.logic.*;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

public class UserPartner extends UserPartnerModel {
    public UserPartner() {
        super();
    }

    public void reset() {
        if (initSkillLevelData()) {
            update();
        }
    }

    // 初始化技能的等级数据，策划改配置时，做相应修改
    public boolean initSkillLevelData() {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        if (partnerMain == null) {
            return false;
        }
        boolean isUpdate = false;

        // 基础技能
        if (partnerMain.takeSkillBaseList() != null) {
            int skillBaseNum = partnerMain.takeSkillBaseList().length;// 基础技能的个数
            JsonArray jsonArray = getSkillBaseLevelArray();// 升级情况
            if (jsonArray.size() != skillBaseNum) {
                putSkillBaseLevel(SkillManager.formatJsonData(jsonArray, skillBaseNum, 1).toString());
                isUpdate = true;
            }
        }


        // 大世界技能
        if (partnerMain.takeSkillWorldList() != null) {
            int skillWorldNum = partnerMain.takeSkillWorldList().length;// 大世界技能的个数
            JsonArray jsonArray2 = getSkillWorldLevelArray();// 升级情况
            if (jsonArray2.size() != skillWorldNum) {
                putSkillWorldLevel(SkillManager.formatJsonData(jsonArray2, skillWorldNum, 1).toString());
                isUpdate = true;
            }
        }


        // 星级技能，升星解锁的技能
        JsonArray jsonArray3 = getSkillStarLevelArray();// 升级情况
        int[] starSkill = takeStarSkillList();// 已解锁的星级技能列表
        if (starSkill != null) {
            if (jsonArray3.size() < starSkill.length) {
                for (int i=0; i<starSkill.length; i++) {
                    if (i >= jsonArray3.size()) {
                        if (starSkill[i] > 0) {
                            jsonArray3.add(1);// 已解锁的星级，初始等级是1级
                        } else {
                            jsonArray3.add(0);
                        }
                    }
                }
                putSkillStarLevel(jsonArray3.toString());
                isUpdate = true;
            }
        }


        // 光环技能
        if (partnerMain.takeSkillHaloList() != null) {
            int skillHaloNum = partnerMain.takeSkillHaloList().length;// 光环技能的个数
            JsonArray jsonArray4 = getSkillHaloLevelArray();// 升级情况
            if (jsonArray4.size() != skillHaloNum) {
                putSkillHaloLevel(SkillManager.formatJsonData(jsonArray4, skillHaloNum, 1).toString());
                isUpdate = true;
            }
        }

        return isUpdate;
    }

    public UserPartner(long userId, int partnerId) {
        super();
        putUserId(userId);
        putPartnerId(partnerId);
        putLevel(1);// 初始等级1级
        putMaxLevel(PartnerManager.getFirstMaxLevel());
    }

    public PBUserPartner.Builder takeBuilder() {
        PBUserPartner.Builder sb = super.takeBuilder();
        addDetailData(sb);
        sb.setSoldier(takeSoldierMax());
        return sb;
    }

    public PBUserPartner.Builder takeInitBuilder() {
        PBUserPartner.Builder sb = super.takeInitBuilder();
        addDetailData(sb);
        sb.setSoldier(takeSoldierMax());
        return sb;
    }

    public void addDetailData(PBUserPartner.Builder sb) {
        // 资质面板
        sb.putTalent(PartnerConstant.DETAIL_KEY_BASE, takeTalentBase() + "");// 基础资质,读取partner_main配置表
        sb.putTalent(PartnerConstant.DETAIL_KEY_WEAPON_CV, getWeaponTalent() + "");// 取userweapon表的talent
        sb.putTalent(PartnerConstant.DETAIL_KEY_SKILL_CV, takeTalentSkill() + "");// 技能加成，基础技能+星级技能
        sb.putTalent(PartnerConstant.DETAIL_KEY_ITEM_CV, getItemTalent() + "");// 取Item_talent,使用加资质类型的道具,会更新这个字段
        sb.putTalent(PartnerConstant.DETAIL_KEY_BREAK_CV, takeTalentBreak() + "");//突破,根据突破几次来计算

        // 战力面板
        UserPower userPower = GameUser.getUserPower(getUserId());
        sb.putPower(PartnerConstant.DETAIL_KEY_WEAPON_PER,  getWeaponAdd2() + "");// 取userweapon表的技能 百分比加成
        sb.putPower(PartnerConstant.DETAIL_KEY_SKILL_CV, getSkillAdd() + "");// 干员技能加成 固定值
        sb.putPower(PartnerConstant.DETAIL_KEY_SKILL_PER, getSkillAdd2() + "");// 干员技能加成 百分比
        sb.putPower(PartnerConstant.DETAIL_KEY_ITEM_CV, getItemPower() + "");// 取Item_power,使用加战力固定值的道具,会更新这个字段
        sb.putPower(PartnerConstant.DETAIL_KEY_SECR_CV, getSecrAdd() + "");// 秘书战力加成 加固定值
        sb.putPower(PartnerConstant.DETAIL_KEY_SECR_PER, getSecrAdd2() + "");// 秘书战力加成 百分比加成
        sb.putPower(PartnerConstant.DETAIL_KEY_STAR_CV, getStarAddCv() + "");// 星级战力加成 加固定值
        sb.putPower(PartnerConstant.DETAIL_KEY_STAR_PER, getStarAddPer() + "");// 星级战力加成 百分比加成
        sb.putPower(PartnerConstant.DETAIL_KEY_SNATCH_CV, getSnatchAdd() + "");// 物质争夺模块增加战力固定值
        sb.putPower(PartnerConstant.DETAIL_KEY_HALO_PER, countHaloAddPer(userPower) + "");// 光环技能加成 百分比

    }


    // 升级会改变战力,城市收益,需要下发给客户端
    public long addLevel(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, int value) {
        super.addLevel(value);
        return reCountPower(userInfo, userPower);
    }

    // 突破会改变战力,城市收益,需要下发给客户端
    public long addBreakNum(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, int value) {
        super.addBreakNum(value);
        // 突破会增加干员资质
        PartnerBreakthrough partnerBreakthrough = PartnerManager.getPartnerBreakthrough(getBreakNum() + 1);// 初始是100,id=1, 突破1次,取id=2
        MainTaskManager.addTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_141, partnerBreakthrough.getTalentAdd());// 更新主线任务,成就,日常任务的进度
        RankActManager.addTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_141, partnerBreakthrough.getTalentAdd());

        RankActManager.addUserrank(userInfo.getServerId(), ActTopRanking.RANK_TYPE_PARTNER_POWER, userInfo, PartnerManager.getPartnerTotalPower(userId), false);
        RankActManager.addUserCrossRank(userInfo, userInfo.getServerId(), ActTopRanking.RANK_TYPE_PARTNER_POWER, PartnerManager.getPartnerTotalPower(userId), false);
        return reCountPower(userInfo, userPower);
    }

    // 使用道具增加干员的战力,影响城市收益,需要下发给客户端
    public long updateItemPower(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, int value) {
        super.addItemPower(value);
        return reCountPower(userInfo, userPower);
    }

    // 干员技能总的加的,委派时加的城市收益 charType 是作用对像的性格
    public int countSkillAddEarn() {
        return SkillManager.getSkillValueBySkillList(takeBaseSkillList(), getSkillBaseLevelArray(), SkillConstant.EFFECT_TYPE_3, 0);
    }

    // 更新 物资争夺挑战胜利的战力加成
    public long updateSnatchAdd(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, long addValue) {
        super.addSnatchAdd(addValue);
        return reCountPower(userInfo, userPower);
    }

    // 武器加成有变动,weapondbid这个字段,装备或是卸下武器 返回战力变更的值
    public long getUpdateWeaponAdd(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, UserWeapon userWeapon) {
        if (userWeapon == null && getWeaponDbid() != 0) {// 卸下武器
            putWeaponDbid(0);
            putWeaponTalent(0);
            putWeaponAdd2(0);
        }

        if (userWeapon != null) {// 武器加成有变更
            if (getWeaponDbid() != userWeapon.getId()) {
                super.putWeaponDbid(userWeapon.getId());
            }
            if (getWeaponTalent() != userWeapon.getTalent()) {
                int addTalent = getWeaponTalent() - userWeapon.getTalent();// 增加的资质
                MainTaskManager.addTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_141, addTalent);// 更新主线任务,成就,日常任务的进度
                RankActManager.addTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_141, addTalent);
                super.putWeaponTalent(userWeapon.getTalent());
            }
            int newAdd2 = takePowerWeapon(userWeapon);// 新的战力加成百分比
            if (getWeaponAdd2() != newAdd2) {
                super.putWeaponAdd2(newAdd2);
            }
        }
        return reCountPower(userInfo, userPower);
    }

    // 武器加成有变动,weapondbid这个字段,装备或是卸下武器
    public void updateWeaponAdd(PBUserData.Builder pbUserData, UserInfo userInfo, UserPower userPower, UserWeapon userWeapon) {
        long addValue = getUpdateWeaponAdd(pbUserData, userInfo, userPower, userWeapon);
        if (addValue != 0) {// 战力有变动
            long newPower = userPower.getPower() + addValue;// 玩家基础战力增加
            userPower.handlePowerChange(pbUserData, userInfo, newPower);// 更新玩家的总战力
        }
    }

    // 重算干员战力 返回增加的值 秘书羁绊会影响多个干员，物资争夺挑战会影响所有上阵的干员
    public long reCountPower(UserInfo userInfo, UserPower userPower) {
        long newPower = GameUser.countPowerByPartner(userInfo.getId(), getPartnerId(), this, userPower, 0);
        //System.out.println("newPower:" + newPower + " oldPower:" + getTotalPower());
        long addPower = newPower - getTotalPower();
        if (newPower != getTotalPower()) {// 新算出来的战力 不等于 旧战力
            super.putTotalPower(newPower);
        }
        return addPower;
    }


    // 干员的基础资质
    public int takeTalentBase() {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        if (partnerMain == null) {
            return 0;
        }
        return partnerMain.getTalent();
    }

    // 突破 增加的总资质
    public int takeTalentBreak() {
        int count = 0;
        for (int i=0; i<getBreakNum(); i++) {
            PartnerBreakthrough partnerBreakthrough = PartnerManager.getPartnerBreakthrough(i+2);// 取下一级的talent_add
            count += partnerBreakthrough.getTalentAdd();
        }
        return count;
    }

    // 基础技能和 星级技能增加的基础资质 charType 是作用对像的性格
    public int takeTalentSkill() {
        // 基础技能加的资质
        int baseSkillAdd = SkillManager.getSkillValueBySkillList(takeBaseSkillList(), getSkillBaseLevelArray(), SkillConstant.EFFECT_TYPE_2, 0);

        // 星级技能加的资质
        int starSkillAdd = SkillManager.getSkillValueBySkillList(takeStarSkillList(), getSkillStarLevelArray(), SkillConstant.EFFECT_TYPE_2, 0);

        return baseSkillAdd + starSkillAdd;
    }

    // 获取总的资质 基础资质+武器加的资质+干员突破加的资质+技能(type=4)加的资质+使用道具加的资质 + 秘书
    public int takeTotalTalent() {
        int total = takeTalentBase() + getWeaponTalent() + takeTalentBreak() + takeTalentSkill() + getItemTalent();
        return total;
    }

    // 干员的基础战力 总资质 * 资质提升系数(根据 level 读取partner_power 表的pownum)
    public long takePowerBase() {
        int talent = takeTotalTalent();// 总的资质
        PartnerLevelUp partnerLevelUp = PartnerManager.getPartnerLevelUp(getLevel());
        long total = talent * partnerLevelUp.getPowerNum();
        if (total != getBasePower()) {
            putBasePower(total);
        }
        return total;
    }


    // 总的加成, 固定值 使用道具加固定值,干员技能加固定值,秘书技能加固定值,升星加固定值, 物资争夺挑战胜利的战力加成
    public long takeTotalAddCv() {
        return getItemPower() + getSkillAdd() + getSecrAdd() + getStarAddCv() + getSnatchAdd();
    }

    // 总的加成 百分比 统一放大1W倍 武器加百分比,干员技能加百分比,秘书技能加百分比,升星加百分比,光环技能增加的百分比
    public int takeTotalAddPer(UserPower userPower) {
        return getWeaponAdd2() + getSkillAdd2() + getSecrAdd2() + getStarAddPer() + countHaloAddPer(userPower);
    }

    // 统计光环技能对战力总的有多少加成 只统计 effect_type=1。effect_type=45的加成放在userpower那边进行累加
    public int countHaloAddPer(UserPower userPower) {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        if (partnerMain == null) {
            return 0;
        }
        int[] haloList = partnerMain.takeSkillHaloList();// 光环技能列表
        if (haloList == null || haloList.length == 0) {
            return 0;
        }

        // 配置在partner_main表的光环技能加成
        int skillAdd = SkillManager.getSkillValueBySkillList(haloList, getSkillHaloLevelArray(), SkillConstant.EFFECT_TYPE_1, 0);

        // 配置在partner_halo表的光环技能加成
        PartnerHalo partnerHalo = PartnerManager.getPartnerHaloByPartnerId(getPartnerId());
        if (partnerHalo != null) {
            int haloSkillId = partnerHalo.getHaloSkill();
            int level = partnerHalo.countSkillLevel(userPower.getPartnerIdArray());
            skillAdd += SkillManager.countSkillValue(haloSkillId, level, SkillConstant.EFFECT_TYPE_1, 0, true);
        }

        return skillAdd;
    }

    // 武器给干员的战力加成 返回百分几
    public int takePowerWeapon(UserWeapon userWeapon) {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        int result = 0;
        if (partnerMain == null) {
            return result;
        }
        if (getWeaponDbid() > 0 && userWeapon != null) {
            JsonArray jsonArray = userWeapon.takeAttAdd();
            for (int i=0;i<jsonArray.size();i++) {
                PBWeaponAtt.Builder pbAtt = PartnerManager.takePBWeaponAtt(jsonArray.getString(i));
                if (pbAtt.getType() == partnerMain.getCharacterType()) {
                    result += pbAtt.getAddValue();
                }
            }
        }
        return result * 100;// 放到100, 500 表示5%
    }

    // 生的小孩带的城市收益加成
    public int takeChildAdd() {
        PartnerBreakthrough partnerBreakthrough = PartnerManager.getPartnerBreakthroughByMaxLevel(getMaxLevel());
        return partnerBreakthrough.getChildAdd();
    }

    // 升星加的战力固定值
    public long getStarAddCv() {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        if (partnerMain == null) {
            return 0L;
        }
        PartnerStar partnerStar = PartnerManager.getPartnerStar(getStar(), partnerMain.getQuality());
        if (partnerStar == null) {
            return 0L;
        } else {
            return partnerStar.getPowerAddValue();
        }
    }

    // 升星加的战力百分比 万倍
    public int getStarAddPer() {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        if (partnerMain == null) {
            return 0;
        }
        PartnerStar partnerStar = PartnerManager.getPartnerStar(getStar(), partnerMain.getQuality());
        if (partnerStar == null) {
            return 0;
        } else {
            return partnerStar.getPowerAddPer();
        }
    }

    // 获取干员的性格名称
    public int getCharacterType() {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        return partnerMain == null ? 0 : partnerMain.getCharacterType();
    }

    // 生成干员快照
    public JsonObject creatPhoto(UserPower userPower) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.put("partnerId", getPartnerId());
        long partnerPower = GameUser.countPowerByPartner(getUserId(), getPartnerId(), this, userPower, 0);// 该干员的战力
        jsonObject.put("totalPower", partnerPower);
        if (getWeaponDbid() > 0) {
            UserWeapon userWeapon = PartnerManager.getUserWeapon(getUserId(), getWeaponDbid());
            if (userWeapon != null) {
                jsonObject.put("weaponId", userWeapon.getWeaponId());
            }
        }
        return jsonObject;
    }

    // 基础技能列表
    public int[] takeBaseSkillList() {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        if (partnerMain == null) {
            return null;
        }
        return partnerMain.takeSkillBaseList();
    }

    // 大世界技能列表
    public int[] takeWorldSkillList() {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        if (partnerMain == null) {
            return null;
        }
        return partnerMain.takeSkillWorldList();
    }

    // 专属技能列表
    public int[] takeExSkStuntillList() {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        if (partnerMain == null) {
            return null;
        }
        return partnerMain.takeSkillExStuntList();
    }

    // 根据effectType 统计大世界技能总的加成值有多少 charType 是作用对像的性格,取出来计算在各模块计算用
    public int countWorldSkillAdd(int effectType, int charType) {
        return SkillManager.getSkillValueBySkillList(takeWorldSkillList(), getSkillWorldLevelArray(), effectType, charType);
    }

    /**
     * 根据effectType 统计模块技能总的加成值有多少 charType 是作用对像的性格,取出来计算在各模块计算用
     * @param effectType 从专属技能取值
     * @param charType
     * @return
     */

    public int countModuleSkillAdd(int effectType, int charType) {
        int[] skillList = takeExSkStuntillList();// 干员的专属技能
        if (skillList == null || skillList.length == 0) {
            return 0;
        }
        JsonArray levelList = new JsonArray();
        for (int i=0; i<skillList.length; i++) {
            levelList.add(takeSkillExStuntLevel());
        }

        return SkillManager.getSkillValueBySkillList(skillList, levelList, effectType, charType);
    }

    // 登录时重算 根据effectType 统计大世界技能总的加成值有多少
    public int initCountWorldSkillAdd(int effectType, int charType) {
        return SkillManager.initCountSkillValue(takeWorldSkillList(), getSkillWorldLevelArray(), effectType, charType);
    }

    // 登录时重算 根据effectType 统计专属技能总的加成值有多少
    public int initCountExstruntkill(int effectType, int charType) {
        int[] skillList = takeExSkStuntillList();// 干员的专属技能
        if (skillList == null || skillList.length == 0) {
            return 0;
        }
        JsonArray levelList = new JsonArray();
        for (int i=0; i<skillList.length; i++) {
            levelList.add(takeSkillExStuntLevel());
        }
        return SkillManager.initCountSkillValue(skillList, levelList, effectType, charType);
    }

    // 干员大世界模块的携带兵力上限
    public int takeSoldierMax() {
        PartnerLevelUp partnerLevelUp = PartnerManager.getPartnerLevelUp(getLevel());
        int addCv = countWorldSkillAdd(SkillConstant.EFFECT_TYPE_101, 0);// 自身带兵数量增加固定值 在userpartner的worldskill
        int addPer = countWorldSkillAdd(SkillConstant.EFFECT_TYPE_102, 0);// 自身带兵数量增加百分比 在userpartner的worldskill
        long total = CommonUtils.countPerValue(partnerLevelUp.getSoldier(), addPer) + addCv;
        return (int)total;
    }

    // 干员对应的碎片id
    public int takeChipId() {
        return getPartnerId() + GameConstant.START_ID_CHIP_MAIN;
    }

    // 干员的品质
    public int takeQuality() {
        PartnerMain partnerMain = PartnerManager.getPartnerMain(getPartnerId());
        return partnerMain.getQuality();
    }

    // 干员最多能升星的阶数 {2,2,4,5,5} N~R的英雄只能提升至2星，SR品质的英雄可以提升至4星，SSR品质以上的英雄可提升至5星
    public int takeMaxStarStage() {
        int quality = takeQuality();// 品质
        int maxStar = Constant.PARTNER_STAR_MAX[quality - 1];
        return maxStar * Constant.PARTNER_STAR_STAGE;// N,R品质的英雄最多升级到10，SR品质的英雄升级到20
    }

    // 干员专属技能的等级，初始是1级，升1星2级，升2星3级
    public int takeSkillExStuntLevel() {
        return getStar() / Constant.PARTNER_STAR_STAGE + 1;
    }

    // 当前干员是几阶，如star=8 表示1星3阶
    public int takeStarStage() {
        return getStar() % Constant.PARTNER_STAR_STAGE;
    }

    // 已解锁的星级技能列表
    public int[] takeStarSkillList() {
        int quality = takeQuality();
        int[] skillList = new int[Constant.PARTNER_STAR_SKILL_MAX + 1];//6个元素从0星开始
        for (int i=0;i<Constant.PARTNER_STAR_SKILL_MAX;i++) {
            int stage = Constant.PARTNER_STAR_STAGE * i;
            PartnerStar partnerStar = PartnerManager.getPartnerStar(stage, quality);
            if (partnerStar != null && getStar() >= partnerStar.getStage()) {
                skillList[i] = partnerStar.getSkillId();
            } else {
                skillList[i] = 0;
            }
        }
        return skillList;
    }
}
